4 Tips React Untuk Meningkatkan Kode Anda Secara Instan
Pengetahuan yang luas tentang React adalah salah satu keterampilan yang paling berharga bagi seorang developer front-end. Banyak perusahaan terus-menerus mencari React developer dan ingin membayar mereka semakin banyak. Itulah mengapa penting untuk terus berkembang sebagai developer, karena ini adalah usaha yang sangat bermanfaat.
Untuk membantu Anda dalam perjalanan Anda, saya ingin berbagi empat tips yang telah membantu saya dalam menulis kode React yang lebih baik. Saya harap Anda akan menemukan sesuatu yang baru dan berguna. Jadi mari kita langsung ke dalamnya!
Daftar isi
- Mengembalikan fungsi dari handler
- Tanggung jawab terpisah
- Gunakan maps objek alih-alih kondisi
- Letakkan variabel independen di luar siklus hidup React
Mengembalikan fungsi dari handler
Jika Anda sudah familiar dengan pemrograman fungsional, Anda tahu apa yang saya bicarakan. Kita dapat dengan mudah menyebutnya "curry" dengan cara tertentu. Intinya, kami menetapkan beberapa parameter fungsi sebelumnya.
Kami memiliki Problem yang jelas dengan kode boilerplate di bawah ini. Teknik itu akan membantu kita!
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: ""
});
// First handler
const handleNameChange = (e) => {
setUser((prev) => ({
...prev,
name: e.target.value
}));
};
// Second handler!
const handleSurnameChange = (e) => {
setUser((prev) => ({
...prev,
surname: e.target.value
}));
};
// Third handler!!!
const handleAddressChange = (e) => {
setUser((prev) => ({
...prev,
address: e.target.value
}));
};
// What if we need one more input? Should we create another handler for it?
return (
<>
<input value={user.name} onChange={handleNameChange} />
<input value={user.surname} onChange={handleSurnameChange} />
<input value={user.address} onChange={handleAddressChange} />
</>
);
}
Solution
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: ""
});
const handleInputChange = (field) => {
return (e) => {
setUser((prev) => ({
...prev,
[field]: e.target.value
}));
};
};
return (
<>
<input value={user.name} onChange={handleInputChange("name")} />
<input value={user.surname} onChange={handleInputChange("surname")} />
<input value={user.address} onChange={handleInputChange("address")} />
{JSON.stringify(user)}
</>
);
}
Tanggung jawab terpisah
Membuat komponen "deity" adalah kesalahan umum yang dilakukan developer. Disebut "deity" karena mengandung banyak baris kode yang sulit dipahami dan dipelihara. Saya sangat merekomendasikan membagi komponen menjadi beberapa sub-modul independen.
Struktur tipikal untuk ini adalah:
- Modul UI, hanya bertanggung jawab untuk representasi visual.
- Modul model, hanya berisi logika bisnis. Contohnya adalah pengait khusus.
- Modul Lib, berisi semua utilitas yang diperlukan untuk komponen tersebut.
Berikut adalah contoh demo kecil untuk membantu mengilustrasikan konsep ini.
export function ListComponent() {
// Our local state
const [list, setList] = useState([]);
// Handler to load data from the server
const fetchList = async () => {
try {
const resp = await fetch("https://www.url.com/list");
const data = await resp.json();
setList(data);
} catch {
showAlert({ text: "Something went wrong!" });
}
};
// We want to fetch only on mount
useEffect(() => {
fetchList();
}, []);
// Handler responsible for deleting items
const handleDeleteItem = (id) => {
return () => {
try {
fetch(`https://www.url.com/list/${id}`, {
method: "DELETE"
});
setList((prev) => prev.filter((x) => x.id !== id));
} catch {
showAlert({ text: "Something went wrong!" });
}
};
};
// Here we just render our data items
return (
<div className="list-component">
{list.map(({ id, name }) => (
<div key={id} className="list-component__item>">
{/* We want to trim long name with ellipsis */}
{name.slice(0, 30) + (name.length > 30 ? "..." : "")}
<div onClick={handleDeleteItem(id)} className="list-component__icon">
<DeleteIcon />
</div>
</div>
))}
</div>
);
}
Kita harus mulai dengan menulis utilitas kita yang akan digunakan dalam model dan modul UI.
export async function getList(onSuccess) {
try {
const resp = await fetch("https://www.url.com/list");
const data = await resp.json();
onSuccess(data)
} catch {
showAlert({ text: "Something went wrong!" });
}
}
export async function deleteListItem(id, onSuccess) {
try {
fetch(`https://www.url.com/list/${id}`, {
method: "DELETE"
});
onSuccess()
} catch {
showAlert({ text: "Something went wrong!" });
}
}
export function trimName(name) {
return name.slice(0, 30) + (name.lenght > 30 ? '...' : '')
Sekarang kita perlu mengimplementasikan logika bisnis kita. Ini hanya akan menjadi pengait khusus yang mengembalikan hal-hal yang kita butuhkan.
export function useList() {
const [list, setList] = useState([]);
const handleDeleteItem = useCallback((id) => {
return () => {
deleteListItem(id, () => {
setList((prev) => prev.filter((x) => x.id !== id));
})
};
}, []);
useEffect(() => {
getList(setList);
}, []);
return useMemo(
() => ({
list,
handleDeleteItem
}),
[list, handleDeleteItem]
);
}
Langkah terakhir adalah menulis modul UI kita dan kemudian menggabungkan semuanya.
export function ListComponentItem({ name, onDelete }) {
return (
<div className="list-component__item>">
{trimName(name)}
<div onClick={onDelete} className="list-component__icon">
<DeleteIcon />
</div>
</div>
);
}
export function ListComponent() {
const { list, handleDeleteItem } = useList();
return (
<div className="list-component">
{list.map(({ id, name }) => (
<ListComponentItem
key={id}
name={name}
onDelete={handleDeleteItem(id)}
/>
))}
</div>
);
}
Gunakan maps objek alih-alih kondisi
Jika Anda perlu menampilkan berbagai elemen tergantung pada variabelnya, Anda dapat menerapkan tip itu. Menggunakan strategi yang mudah ini membuat komponen menjadi lebih deklaratif dan menyederhanakan pemahaman kode. Selain itu, membuatnya lebih tidak menyakitkan untuk memperluas fungsionalitas lebih jauh.
Problem
Jangan lupa berlangganan untuk mempelajari hal-hal penting tentang Frontend!
function Account({type}) {
let Component = UsualAccount
if (type === 'vip') {
Component = VipAccount
}
if (type === 'moderator') {
Component = ModeratorAccount
}
if (type === 'admin') {
Component = AdminAccount
}
return (
<div className='account'>
<Component />
<AccountStatistics />
</div>
)
}
Solution
const ACCOUNTS_MAP = {
'vip': VipAccount,
'usual': UsualAccount,
'admin': AdminAccount,
'moderator': ModeratorAccount,
}
function Account({type}) {
const Component = ACCOUNTS_MAP[type]
return (
<div className='account'>
<Component />
<AccountStatistics />
</div>
)
}
Letakkan variabel independen di luar siklus hidup React
Idenya adalah untuk memisahkan logika yang tidak membutuhkan metode siklus hidup komponen React dari komponen itu sendiri. Ini meningkatkan kejelasan kode dengan membuat dependensi menjadi lebih eksplisit. Oleh karena itu, menjadi lebih mudah untuk membaca dan memahami komponen-komponennya.
Problem
function useItemsList() {
const defaultItems = [1, 2, 3, 4, 5]
const [items, setItems] = useState(defaultItems)
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter(el => el !== val) : [...arr, val];
}
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num))
}
}
return {
items,
handleToggleItem,
}
}
Solution
const DEFAULT_ITEMS = [
1, 2, 3, 4, 5
]
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter(el => el !== val) : [...arr, val];
}
function useItemsList() {
const [items, setItems] = useState(DEFAULT_ITEMS)
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num))
}
}
return {
items,
handleToggleItem,
}
}