Komponen bawaan peramban <input> memungkinkan Anda me-render berbagai jenis masukan form.

<input />

Referensi

<input>

Untuk menampilkan sebuah masukan, render komponen bawaan peramban <input>.

<input name="myInput" />

Lihat lebih banyak contoh di bawah ini.

Props

<input> mendukung semua element props yang umum.

Anda dapat membuat sebuah masukan yang terkontrol melalui satu dari beberapa props berikut:

  • checked: Sebuah boolean. Untuk masukan checkbox atau tombol radio, mengontrol apakah itu dipilih.
  • value: Sebuah string. Untuk sebuah masukan teks, mengontrol teks. (Untuk tombol radio, menentukan data form.)

Ketika Anda mengoper salah satu dari mereka, Anda juga harus mengoper sebuah onChange handler yang memperbarui nilai yang dioper.

Props <input> ini hanya relevan untuk masukan yang tidak dikontrol:

Props <input> ini relevan untuk masukan tidak terkontrol dan masukan terkontrol:

  • accept: Sebuah string. Menentukan tipe file mana yang diterima oleh masukan type="file".
  • alt: Sebuah string. Menentukan teks gambar alternatif untuk masuk type="image".
  • capture: Sebuah string. Menentukan media (mikrofon, video, atau kamera) yang ditangkap oleh masukan type="file".
  • autoComplete: Sebuah string. Menentukan salah satu kemungkinan perilaku autocomplete.
  • autoFocus: Sebuah boolean. Jika true, React akan memfokuskan elemen saat pasang.
  • dirname: Sebuah string. Menentukan nama bidang form untuk arah elemen.
  • disabled: Sebuah boolean. Jika true, masukan tidak akan interaktif dan akan tampak redup.
  • children: <input> tidak menerima children.
  • form: Sebuah string. Menentukan id dari <form> milik masukan ini. Jika dihilangkan, menggunakan parent form terdekat.
  • formAction: Sebuah string. Menimpa parent <form action> dari type="submit" dan type="image".
  • formEnctype: Sebuah string. Menimpa parent <form enctype> dari type="submit" dan type="image".
  • formMethod: Sebuah string. Menimpa parent <form method> dari type="submit" dan type="image".
  • formNoValidate: Sebuah string. Menimpa parent <form noValidate> dari type="submit" dan type="image".
  • formTarget: Sebuah string. Menimpa parent <form target> dari type="submit" dan type="image".
  • height: Sebuah string. Menentukan tinggi dari gambar untuk type="image".
  • list: Sebuah string. Menentukan id dari <datalist> dengan opsi autocomplete.
  • max: Sebuah angka. Menentukan nilai maksimum masukan numerik dan waktu.
  • maxLength: Sebuah angka. Menentukan panjang maksimum teks dan masukan lainnya.
  • min: Sebuah angka. Menentukan nilai minimum masukan numerik dan waktu.
  • minLength: Sebuah angka. Menentukan panjang minimum teks dan masukan lainnya.
  • multiple: Sebuah boolean. Menentukan apakah beberapa nilai diperbolehkan untuk <type="file" dan type="email".
  • name: Sebuah string. Menentukan nama dari masukan yang disubmit dengan form.
  • onChange: Sebuah fungsi Event handler. Dibutuhkan untuk masukan yang terkontrol. Langsung aktif ketika nilai masukan diubah oleh pengguna (sebagai contoh, menyala di setip penekanan tombol). Berperilaku seperti eventinput.
  • onChangeCapture: Sebuha versi dari onChange yang aktif dalam fase menangkap.
  • onInput: Sebuah fungsi Event handler. Langsung aktif ketika nilainya diubah oleh pengguna. Untuk alasan historis, dalam React menggunakan onChange sebagai gantinya yang berfungsi serupa adalah idiomatis.
  • onInputCapture: A version of onInput that fires in the capture phase.
  • onInvalid: Sebuah fungsi Event handler. Aktif jika sebuah masukan gagal divalidasi ketika pengiriman form. Tidak seperti event invalid bawaan, React onInvalid berbentuk event bubbles.
  • onInvalidCapture: Sebuah versi dari onInvalid yang aktif didalam fase menangkap.
  • onSelect: Sebuah fungsi Event handler. Aktif setelah pemilihan di dalam <input> berubah. React memperluas event onSelect untuk juga mengaktifkan pemilihan kosong dan pada pengeditan (yang dapat memengaruhi pemilihan).
  • onSelectCapture: Sebuah versi dari onSelect yang aktif ketika fase menangkap.
  • pattern: Sebuah string. Menentukan pola yang harus cocok dengan value.
  • placeholder: Sebuah string. Ditampilkan dalam warna redup saat nilai input kosong.
  • readOnly: Sebuah boolean. Jika true, masukan tidak dapat diedit oleh pengguna.
  • required: Sebuah boolean. Jika true, nilai harus diberikan untuk form yang akan dikirim.
  • size: Sebuah angka. Mirip dengan pengaturan lebar, tetapi unit tergantung pada kontrol.
  • src: Sebuah string. Menentukan sumber gambar untuk masukan type="image".
  • step: Angka positif atau string 'any'. Menentukan jarak antara nilai yang valid.
  • type: Sebuah string. Satu dari tipe masukan.
  • width: Sebuah string. Menentukan lebar gambar untuk masukan type="image".

Caveats

  • Checkbox harus checked (atau defaultChecked), bukan value (atau defaultValue).
  • Jika sebuah masukan teks menerima sebuah prop string value, itu akan diperlakukan sebagai terkontrol.
  • Jika sebuah checkbox atau sebuah tombol radio menerima prop boolean checked, itu akan diperlakukan sebagai terkontrol.
  • Masukan tidak dapat dikontrol dan tidak dikontrol secara bersamaan.
  • Masukan tidak dapat beralih antara dikontrol atau tidak dikontrol selama masa pakainya.
  • Setiap masukan yang dikontrol membutuhkan event handler onChange yang secara sinkron memperbarui nilai pendukungnya.

Penggunaan

Menampilkan masukan dari berbagai jenis

Untuk menampilkan masukan, render sebuah komponen <input>. Secara default, itu akan menjadi masukan teks. Anda dapat mengopen type="checkbox" untuk sebuah checkbox, type="radio" untuk sebuah tombol radio, atau salah satu dari jenis masukan lainnya.

export default function MyForm() {
  return (
    <>
      <label>
        Masukan teks: <input name="myInput" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" />
      </label>
      <hr />
      <p>
        Tombol radio:
        <label>
          <input type="radio" name="myRadio" value="option1" />
          Pilihan 1
        </label>
        <label>
          <input type="radio" name="myRadio" value="option2" />
          Pilihan 2
        </label>
        <label>
          <input type="radio" name="myRadio" value="option3" />
          Pilihan 3
        </label>
      </p>
    </>
  );
}


Memberikan label untuk sebuah masukan

Biasanya, Anda akan menaruh setiap <input> di dalam sebuah tag <label>. Ini memberi tahu peramban bahwa label ini dikaitkan dengan masukan itu. Saat pengguna melakukan klik pada label, peramban akan secara otomatis memfokuskan input. Ini juga penting untuk aksesibilitas: pembaca layar akan memberitahukan keterangan label saat pengguna memfokuskan masukan terkait.

Jika Anda tidak dapat menumpuk <input> pada sebuah <label>, katikan keduanya dengan mengoper ID yang sama ke <input id> dan <label htmlFor>. Untuk menghindari konflik antara beberapa instance dari satu komponen, buat ID tersebut dengan useId.

import { useId } from 'react';

export default function Form() {
  const ageInputId = useId();
  return (
    <>
      <label>
        Nama depan Anda:
        <input name="firstName" />
      </label>
      <hr />
      <label htmlFor={ageInputId}>Umur Anda:</label>
      <input id={ageInputId} name="age" type="number" />
    </>
  );
}


Memberikan nilai awal untuk sebuah masukan

Secara opsional Anda dapat menentukan nilai awal untuk masukan apa pun. Berikan sebagai string defaultValue untuk masukan teks. Sedangkan checkboxes dan tombol radio harus menentukan nilai awal dengan boolean defaultChecked.

export default function MyForm() {
  return (
    <>
      <label>
        Masukan teks: <input name="myInput" defaultValue="Beberapa nilai awal" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
      </label>
      <hr />
      <p>
        Tombol radio:
        <label>
          <input type="radio" name="myRadio" value="option1" />
          Pilihan 1
        </label>
        <label>
          <input
            type="radio"
            name="myRadio"
            value="option2"
            defaultChecked={true} 
          />
          Pilihan 2
        </label>
        <label>
          <input type="radio" name="myRadio" value="option3" />
          Pilihan 3
        </label>
      </p>
    </>
  );
}


Membaca nilai input saat mengirimkan form

Tambahkan sebuah <form> disekitar masukan Anda dengan <button type="submit"> di dalamnya. Ini akan memanggil event handler <form onSubmit>. Secara default, peramban akan mengirimkan data form ke URL saat ini dan menyegarkan halaman. Anda dapat menimpa perilaku tersebut dengan memanggil e.preventDefault(). Baca data form dengan new FormData(e.target).

export default function MyForm() {
  function handleSubmit(e) {
    // Cegah peramban memuat ulang halaman
    e.preventDefault();

    // Membaca data form
    const form = e.target;
    const formData = new FormData(form);

    // Anda dapat mengoper formData sebagai fetch body secara langsung:
    fetch('/some-api', { method: form.method, body: formData });

    // Atau Anda dapat mengerjakannya sebagai objek biasa:
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson);
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        Masukan teks: <input name="myInput" defaultValue="Beberapa masukan awal" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
      </label>
      <hr />
      <p>
        Tombol radio:
        <label><input type="radio" name="myRadio" value="option1" /> Pilihan 1</label>
        <label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Pilihan 2</label>
        <label><input type="radio" name="myRadio" value="option3" /> Pilihan 3</label>
      </p>
      <hr />
      <button type="reset">Reset form</button>
      <button type="submit">Kirim form</button>
    </form>
  );
}

Note

Berikan name untuk setiap <input>, contohnya <input name="firstName" defaultValue="Taylor" />. name yang Anda tentukan akan digunakan sebagai kunci dalam data form, contohnya { firstName: "Taylor" }.

Pitfall

Secara default, apa pun <button> di dalam sebuah <form> akan melakukan submit. Ini bisa mengejutkan! Jika Anda memiliki komponen React Button kustom Anda sendiri, pertimbangkan untuk mengembalikan <button type="button"> bukannya <button>. Kemudian, secara eksplisit, gunakan <button type="submit"> untuk tombol yang seharusnya mengirimkan form.


Mengontrol input dengan variabel status

Sebuah masukan seperti <input /> tidaklah terkontrol. Bahkan jika Anda memberikan sebuah nilai awal seperti <input defaultValue="Teks awal" />, JSX Anda hanya menentukan nilai awal. Tidak mengontrol apa seharusnya nilai sekarang.

Untuk render sebuah masukan terkontrol, oper prop value ke dalamnya (atau checked untuk checkbox and radio). React akan memaksa masukan untuk selalu memiliki value yang Anda berikan. Biasanya, Anda akan melakukan ini dengan mendeklarasikan sebuah variable state:

function Form() {
const [firstName, setFirstName] = useState(''); // Deklarasikan variabel state...
// ...
return (
<input
value={firstName} // ...memaksa nilai masukan untuk cocok dengan variabel state...
onChange={e => setFirstName(e.target.value)} // ... dan perbarui variabel state pada setiap pengeditan!
/>
);
}

Bagaimanapun sebuah masukan terkontrol masuk akal jika Anda membutuhkan state—contohnya, untuk render-ing ulang UI Anda pada setiap pengeditan:

function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
Nama Anda:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Nama Anda adalah {firstName}.</p>}
...

Ini juga berguna jika Anda ingin menawarkan berbagai cara untuk menyesuaikan state masukan (contohnya, dengan mengeklik tombol):

function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Umur:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Tambah 10 tahun
</button>

value yang Anda berikan ke komponen terkontrol tidak boleh undefined or null. Jika Anda memerlukan nilai awal kosong (seperti dengan kolom firstName di bawah), inisialisasi variabel state Anda ke string kosong ('').

import { useState } from 'react';

export default function Form() {
  const [firstName, setFirstName] = useState('');
  const [age, setAge] = useState('20');
  const ageAsNumber = Number(age);
  return (
    <>
      <label>
        Nama Anda:
        <input
          value={firstName}
          onChange={e => setFirstName(e.target.value)}
        />
      </label>
      <label>
        Umur:
        <input
          value={age}
          onChange={e => setAge(e.target.value)}
          type="number"
        />
        <button onClick={() => setAge(ageAsNumber + 10)}>
          Tambah 10 tahun
        </button>
      </label>
      {firstName !== '' &&
        <p>Nama Anda adalah {firstName}.</p>
      }
      {ageAsNumber > 0 &&
        <p>Umur Anda adalah {ageAsNumber}.</p>
      }
    </>
  );
}

Pitfall

Jika Anda mengoper value tanpa onChange, tidak mungkin bisa untuk mengetik di dalam masukan. Ketika Anda mengontrol sebuah masukan dengan memberikan beberapa value ke dalamnya, Andan memaksanya untuk selalu memiliki nilai yang Anda berikan. Jika Anda mengoper sebuah variabel state sebagai value tetapi lupa untuk memperbarui variabel state tersebut secara sinkron selama onChange event handler, React akan mengembalikan masukan setelah setiap keystroke kembali ke value yang Anda tentukan.


Mengoptimalkan render-ing ulang pada setiap penekanan tombol

Ketika Anda menggunakan masukan terkontrol, Anda mengatur state pada setiap penekanan tombol. Jika komponen yang berisi state Anda me-render ulang pohon besar, ini bisa menjadi lambat. Ada beberapa cara untuk mengoptimalkan kinerja render-ing ulang.

Contohnya, misalkan Anda mulai dengan form yang me-render ulang semua konten halaman pada setiap penekanan tombol:

function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}

Karena <PageContent /> tidak bergantung pada masukan state, Anda dapat memindahkan masukan state ke dalam komponennya sendiri:

function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}

function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}

Ini secara signifikan meningkatkan kinerja karena sekarang hanya SignupForm yang di-render ulang pada setiap penekanan tombol.

Jika tidak ada cara untuk menghindari pe-render-an ulang (contohnya, jika PageContent bergantung pada nilai masukan pencarian), useDeferredValue memungkinkan Anda menjaga masukan yang dikontrol tetap responsif bahkan di tengah render ulang yang besar.


Penyelesaian masalah

Masukan teks saya tidak diperbarui saat saya mengetiknya

Jika Anda me-render masukan dengan value tetapi tanpa onChange, Anda akan melihat kesalahan di konsol:

// 🔴 Bug: masukan teks terkontrol tanpa handler onChange
<input value={something} />
Console
Anda memberikan prop value ke kolom form tanpa handler onChange. Ini akan membuat bidang read-only. Jika bidang harus dapat diubah, gunakan defaultValue. Jika tidak, tetapkan onChange atau readOnly.

Seperti yang disarankan oleh pesan kesalahan, jika Anda hanya ingin menentukan nilai awal, berikan defaultValue sebagai gantinya:

// ✅ Bagus: masukan tidal terkontrol dengan sebuah nilai awal
<input defaultValue={something} />

Jika Anda ingin mengontrol masukan ini menggunakan sebuah variabel state, tentukan sebuah handler onChange:

// ✅ Bagus: masukan terkontrol dengan onChange
<input value={something} onChange={e => setSomething(e.target.value)} />

Jika nilainya sengaja read-only, tambahkan prop readOnly untuk mendiamkan kesalahan:

// ✅ Bagus: masukan yang dikontrol secara readonly tanpa perubahan
<input value={something} readOnly={true} />

Checkbox saya tidak diperbarui ketika saya mengkliknya

Jika Anda me-render kotak checkbox dengan checked tetapi tanpa onChange, Anda akan melihat kesalahan di konsol:

// 🔴 Bug: checkbox terkontrol tanpa handler onChange
<input type="checkbox" checked={something} />
Console
Anda memberikan prop checked ke kolom form tanpa handler onChange. Ini akan membuat bidang read-only. Jika bidang harus dapat diubah, gunakan defaultChecked. Jika tidak, tetapkan onChange atau readOnly.

Seperti yang disarankan oleh pesan kesalahan, jika Anda hanya ingin menentukan nilai awal, berikan defaultValue sebagai gantinya:

// ✅ Bagus: checkbox tidak terkontrol dengan nilai awal
<input type="checkbox" defaultChecked={something} />

Jika Anda ingin mengontrol masukan checkbox ini menggunakan sebuah variabel state, tentukan sebuah handler onChange:

// ✅ Bagus: checkbox terkontrol dengan onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />

Pitfall

Anda perlu membaca e.target.checked daripada e.target.value untuk checkbox.

Jika checkbox sengaja read-only, tambahkan prop readOnly untuk mendiamkan kesalahan:

// ✅ Bagus: readonly controlled input without on change
<input type="checkbox" checked={something} readOnly={true} />

Tanda sisipan saya melompat ke awal pada setiap penekanan tombol

Jika Anda mengontrol sebuah masukan, Anda harus memperbarui variabel state-nya ke nilai masukan dari DOM selama onChange.

Anda tidak dapat memperbaruinya menjadi sesuatu selain e.target.value (atau e.target.checked untuk checkbox):

function handleChange(e) {
// 🔴 Bug: memperbarui masukan ke sesuatu selain e.target.value
setFirstName(e.target.value.toUpperCase());
}

Anda juga tidak dapat memperbaruinya secara asinkron:

function handleChange(e) {
// 🔴 Bug: memperbarui masukan secara asinkron
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}

Untuk memperbaiki kode Anda, perbarui secara sinkron ke e.target.value:

function handleChange(e) {
// ✅ Memperbarui input terkontrol ke e.target.value secara sinkron
setFirstName(e.target.value);
}

Jika ini tidak menyelesaikan masalah, mungkin saja masukan dihapus dan ditambahkan kembali dari DOM pada setiap penekanan tombol. Ini dapat terjadi jika Anda secara tidak sengaja menyetel ulang state pada setiap render ulang, contohnya jika masukan atau salah satu parentnya selalu menerima atribut key yang berbeda, atau jika Anda menyusun definisi fungsi komponen (yang tidak didukung dan menyebabkan komponen “dalam” selalu dianggap pohon yang berbeda).


Saya menerima pesan kesalahan: “Komponen sedang mengubah masukan yang tidak terkontrol menjadi dikontrol”

Jika Anda memberikan value ke komponen, value tersebut harus tetap berupa string selama masa pakainya.

Anda tidak dapat mengoper value={undefined} terlebih dahulu dan kemudian meneruskan value="some string" karena React tidak akan tahu apakah Anda ingin komponen tidak dikontrol atau dikontrol. Komponen yang dikontrol harus selalu menerima string value, bukan null atau undefined.

Jika value Anda berasal dari API atau variabel status, nilai tersebut mungkin diinisialisasi ke null atau undefined. Dalam hal ini, setel ke string kosong ('') pada awalnya, atau berikan value={someValue ?? ''} untuk memastikan value adalah sebuah string.

Demikian pula, jika Anda mengoper checked ke checkbox, pastikan itu selalu sebuah boolean.