4 Tips React Untuk Meningkatkan Kode Anda Secara Instan - CRUDPRO

4 Tips React Untuk Meningkatkan Kode Anda Secara Instan

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!

4 Tips React Untuk Meningkatkan Kode Anda Secara Instan

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,
  }
}