Jika Anda sudah profesional, mungkin ingat kruk Anda. Atau mungkin menawarkan solusi yang lebih baik untuk masalah yang dijelaskan.
Artikel ini akan fokus pada pendapat pribadi saya tentang bagaimana mengatur komposisi komponen.
Mari kita mulai dari yang kecil
Mari pertimbangkan beberapa bentuk abstrak. Maksudnya ada banyak field di form (sekitar 10-15 buah), tapi agar mata tidak lari ke atas, kita akan mengambil form dengan 4 field sebagai contoh.
Objek bertingkat dari tipe berikut tiba di pintu masuk ke komponen:
const unit = {
name: 'unit1',
color: 'red',
size: {
width: 2,
height: 4,
},
}
Pengembang yang tidak berpengalaman (seperti saya di bulan pertama bekerja dengan react) akan melakukan semua ini dalam satu komponen di mana nilai input akan disimpan dalam status:
const Component = ({ values, onSave, onCancel }) => {
const [ state, setState ] = useState({});
useEffect(() => {
setState(values);
}, [ values, setState ]);
return <div className="form-layout">
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, name: value }))
}/>
</div>
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, color: value }))
}/>
</div>
<div className="size">
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, size: { width: value } }))
}/>
</div>
<div className="form-field">
<Input onChange={({ target: { value } }) =>
setState((state) => ({...state, size: { height: value } }))
}/>
</div>
</div>
<div className="buttons">
<Button onClick={() => onSave(state)}>Save</Button>
<Button onClick={() => onCancel()}>Cancel</Button>
</div>
</div>
}
Melihat seberapa cepat pengembang mengatasinya, pelanggan akan menawarkan untuk membuat formulir lain berdasarkan formulir ini, tetapi tanpa blok "ukuran".
Ada 2 opsi (dan keduanya tidak benar):
- Anda dapat menyalin komponen pertama dan menambahkan apa yang hilang atau menghilangkan kelebihannya. Ini biasanya dilakukan ketika mereka tidak mengambil komponen mereka sendiri sebagai dasar dan takut merusak sesuatu di dalamnya.
- Tambahkan pengaturan komponen tambahan ke parameter.
Jika setelah implementasi 3-5 formulir proyek selesai, maka pengembang beruntung.
Tetapi biasanya ini hanyalah permulaan, dan jumlah jamur yang berbeda hanya bertambah.
Maka diperlukan yang serupa, tetapi tanpa blok "warna".
Kemudian yang serupa, tetapi dengan blok "deskripsi" baru.
Kemudian buat beberapa blok untuk membaca saja.
Kemudian bentuk yang serupa harus dimasukkan ke dalam bentuk lain - secara umum, kesedihan, yang terkadang muncul dari ini.
Formulir baru dengan menyalin
Pengembang yang melakukan pendekatan salin-sekitar tentu saja akan cepat mengimplementasikan formulir baru. Meski akan ada kurang dari 10. Tapi kemudian mood akan berangsur-angsur turun.
Apalagi saat terjadi desain ulang. Sesuaikan indentasi antar blok dengan bentuk "sedikit", ubah komponen pemilihan warna. Bagaimanapun, semuanya tidak dapat diramalkan sekaligus, dan banyak keputusan desain harus direvisi setelah penerapannya.
Penting untuk memperhatikan seringnya penyebutan "bentuk yang mirip". Bagaimanapun, produknya adalah satu dan semua cetakan harus serupa. Akibatnya, Anda harus berurusan dengan pekerjaan yang sangat tidak menarik dan rutin pada pengerjaan ulang yang sama di setiap formulir, dan omong-omong, penguji juga perlu memeriksa ulang setiap formulir.
Secara umum, Anda mengerti. Jangan salin komponen serupa.
Bentuk baru dengan generalisasi
Jika pengembang memilih jalur kedua, maka tentu saja dia berada di atas kuda - Anda mungkin berpikir. Ini hanya memiliki beberapa komponen yang dapat Anda gunakan untuk menggambar lusinan bentuk. Perbaiki lekukan di seluruh proyek atau ubah komponen "warna" - ini untuk memperbaiki dua baris dalam kode dan penguji harus memeriksa ulang hanya di beberapa tempat.
Namun nyatanya, jalur ini memunculkan komponen yang sangat sulit dipertahankan.
Sulit untuk menggunakannya, tk. banyak parameter, beberapa disebut hampir sama, untuk memahami apa tanggung jawab masing-masing parameter, Anda perlu masuk ke bagian dalam.
<Component
isNameVisible={true}
isNameDisabled={true}
nameLabel="Model"
nameType="input"
isColorVisible={true}
isColorDisabled={false}
colorType={'dropdown'}
isSizeVisible={true}
isHeightVisible={true}
isWidthDisabled={false}
/>
Itu juga sulit untuk dipertahankan. Sebagai aturan, jalinan kondisi yang kompleks di dalam dan penambahan kondisi baru dapat merusak yang lainnya. Mengutak-atik komponen untuk menghasilkan satu bentuk dapat merusak bentuk lainnya.
Secara umum, Anda mengerti. Jangan membuat komponen menjadi banyak properti.Untuk mengatasi masalah opsi kedua, pengembang memulai apa? Baik. Sebagai pengembang sejati, mereka mulai mengembangkan sesuatu yang memudahkan untuk menyiapkan komponen yang kompleks.
Misalnya, mereka membuat parameter bidang (baik, seperti kolom di tabel-react). Dan parameter bidang dilewatkan di sana: bidang mana yang terlihat, mana yang tidak dapat diedit, nama bidang.
Panggilan komponen berubah menjadi ini:
const FIELDS = {
name: { visible: true, disabled: true, label: 'Model', type: 'input' },
color: { visible: true, disabled: false, type: 'dropdown' },
size: { visible: true },
height: { visible: true },
width: { disabled: false },
}
<Component
values={values}
fields={FIELDS}
/>
Alhasil, sang developer bangga pada dirinya sendiri. Dia menggeneralisasi pengaturan untuk semua bidang dan mengoptimalkan kode internal komponen: sekarang untuk setiap bidang, satu fungsi dipanggil, yang mengubah konfigurasi menjadi props dari komponen yang sesuai. Bahkan berdasarkan nama tipenya, komponen yang berbeda membuat. Sedikit lagi dan Anda akan mendapatkan kerangka kerja Anda sendiri.
Keren? Terlalu banyak.
Semoga tidak berubah menjadi ini:
const FIELDS = {
name: getInputConfig({ visible: true, disabled: true, label: 'Model'}),
color: getDropDownConfig({ visible: true, disabled: false}),
size: getBlockConfig({ visible: true }),
height: getInputNumberConfig({ visible: true }),
width: getInputNumberConfig({ disabled: false }),
}
<Component
values={values}
fields={FIELDS}
/>
Secara umum, Anda mengerti. Jangan menemukan kembali roda.
Bentuk baru dengan menggabungkan komponen dan bentuk bersarang
Mari kita ingat apa yang masih kita tulis. Kami sudah memiliki perpustakaan react. Tidak perlu menciptakan desain baru. Konfigurasi komponen di react dijelaskan menggunakan markup JSX
const Form1 = ({ values }) => {
return <FormPanel>
<FormField disabled label=”Model”>
<Input name="name" />
</FormField>
<FormField disabled label=”Color”>
<DropDown name="color" />
</FormField>
<FormPanel>
<FormField disabled label="Height">
<Input name="height" />
</FormField>
<FormField disabled label="Width">
<Input name="width" />
</From Field>
</FormPanelt>
</FormPanel>
}
Sepertinya kita kembali ke opsi penyalinan pertama. Tapi sebenarnya tidak. Ini adalah komposisi yang menghilangkan masalah dari dua pendekatan pertama.
Ada satu set batu bata dari mana bentuk itu dirakit. Setiap batu bata bertanggung jawab atas sesuatu yang berbeda. Beberapa untuk tata letak dan tampilan, beberapa untuk entri data.
Jika Anda perlu mengubah indentasi di seluruh proyek, maka cukup melakukannya di komponen FormField. Jika Anda perlu mengubah pekerjaan daftar drop-down, maka ini dilakukan di satu tempat di komponen DropDown.
Jika Anda membutuhkan bentuk yang serupa, tetapi misalnya, agar tidak ada bidang "warna", maka kami menempatkan balok umum di batu bata terpisah dan merakit bentuk lain.
Kami memindahkan blok Ukuran menjadi komponen terpisah:
const Size = () => <FormPanel>
<FormField disabled label="Height">
<Input name="height" />
</FormField>
<FormField disabled label=”Width”>
<Input name="width" />
</From Field>
</FormPanel>
Membuat bentuk dengan pilihan warna:
const Form1 = () => <FormPanel>
<FormField disabled label="Color">
<DropDown name="color" />
</FormField>
<FormField disabled label="Model">
<Input name="name" />
</FormField>
<Size name="size" />
</FormPanel>
Kami membuat bentuk yang serupa, tetapi tanpa memilih warna:
const Form2 = () => <FormPanel>
<FormField disabled label="Model">
<Input name="name" />
</FormField>
<Size name="size" />
</FormPanel>
Yang terpenting, orang yang mendapatkan kode seperti itu tidak perlu berurusan dengan konfigurasi fiktif pendahulunya. Semuanya ditulis dalam JSX, familiar bagi setiap developer react, dengan petunjuk parameter untuk setiap komponen.
Secara umum, Anda mengerti. Gunakan JSX dan komposisi komponen.
Beberapa kata tentang State
Sekarang mari kita perhatikan negara. Lebih tepatnya, ketidakhadirannya. Segera setelah kami menambahkan status, kami menutup aliran data dan menjadi lebih sulit untuk menggunakan kembali komponen. Semua bata harus stateless (yaitu stateless). Dan hanya pada tingkat tertinggi, bentuk yang dirakit dari batu bata dapat dihubungkan ke negara bagian. Jika bentuknya kompleks, maka masuk akal untuk membaginya menjadi beberapa wadah dan menghubungkan setiap bagian ke redux.
Jangan malas membuat komponen formulir stateless terpisah. Kemudian Anda akan memiliki kesempatan untuk menggunakannya sebagai bagian dari formulir lain, atau membuat formulir penuh status berdasarkan itu, atau wadah untuk menghubungkan ke redux.
Tentu saja, dalam batu bata bisa ada status untuk menyimpan keadaan internal yang tidak terkait dengan aliran data umum. Misalnya, dalam kondisi internal DropDown (daftar drop-down) akan lebih mudah untuk menyimpan atribut apakah itu diperluas atau tidak.
Secara umum, Anda mengerti. Pisahkan komponen menjadi Stateless dan Statefull.
Total
Tidak mengherankan, saya secara berkala menemukan semua kesalahan yang dijelaskan dalam artikel dan masalah yang muncul darinya. Saya harap Anda tidak akan mengulanginya dan memelihara kode Anda akan menjadi lebih mudah.
Saya akan mengulangi poin utama:
- Jangan salin komponen serupa. Gunakan prinsip KERING.
- Jangan membuat komponen dengan banyak properti dan fungsionalitas. Setiap komponen harus bertanggung jawab atas sesuatu yang berbeda (Tanggung Jawab Tunggal dari SOLID)
- Pisahkan komponen menjadi Stateless dan Statefull.
- Jangan menemukan kembali desain Anda. Gunakan JSX dan komposisi dari komponen Anda.