Saya sedang mengerjakan aplikasi yang sangat bergantung pada input data sehingga saya harus membuat berbagai jenis objek dengan data yang diperlukan dan tidak diperlukan, dan bagian data yang tidak diperlukan adalah masalah saya di sini, karena ini menyebabkan banyak tambahan kode dan saya bertanya-tanya apakah ada cara untuk menghindari ini.

Di sini saya memiliki formulir yang memiliki 6 bidang (hanya satu contoh, tetapi saya memiliki kasus yang sama di banyak tempat lain di aplikasi), 2 di antaranya diperlukan, sisanya tidak, dan saya menulis fungsi ini untuk menangani objek penciptaan:

  const handleAddSupplier = (e) => {
    e.preventDefault();
    const formData = e.target.elements;

    const supplierData = {
      name: formData.name.value,
      companyId: formData.companyId.value,
      ...((formData.country.value || formData.city.value || formData.postalCode.value || formData.street.value) && {
        address: {
          ...(formData.country.value && { country: formData.country.value }),
          ...(formData.city.value && { city: formData.city.value }),
          ...(formData.postalCode.value && { postalCode: formData.postalCode.value }),
          ...(formData.street.value && { street: formData.street.value }),
        },
      }),
    };

    console.log(supplierData);
  };

Dan itu berhasil, tetapi menurut saya terlalu banyak kode, saya curiga ada cara yang lebih mudah untuk melakukan ini.

Adapun “tanda tangan” dari objek yang harus dibuat adalah:

{
  name: "",
  companyId: "",
  address: {
    country: "",
    city: "",
    postalCode: "",
    street: ""
  }
}

Objek alamat dan bidangnya sepenuhnya opsional, jadi jika tidak ada bidang alamat yang tersedia (yaitu pengguna hanya memasukkan bidang yang diperlukan dan tidak ada yang lain), objek alamat tidak boleh dibuat sama sekali, bahkan sebagai objek kosong. .

Kode saya berfungsi, saya hanya tertarik untuk melihat apakah ada cara lain yang lebih sederhana.

Sunting: Saya sedikit merusak objek dan menyelamatkan diri saya beberapa tulisan, tetapi tetap saja, bagaimana jika saya memiliki 10 bidang yang tidak diperlukan, apakah saya secara kondisional "ATAU" semuanya 10?

const { name, companyId, country, city, postalCode, street } = e.target.elements;

const supplierData = {
  name: name.value,
  companyId: companyId.value,
  ...((country.value || city.value || postalCode.value || street.value) && {
    address: {
      ...(country.value && { country: country.value }),
      ...(city.value && { city: city.value }),
      ...(postalCode.value && { postalCode: postalCode.value }),
      ...(street.value && { street: street.value }),
    },
  }),
};

Atau cara lain untuk menulis hal yang sama:

const {
  name: { value: name },
  companyId: { value: companyId },
  country: { value: country },
  city: { value: city },
  postalCode: { value: postalCode },
  street: { value: street },
} = e.target.elements;

const supplierData = {
  name: name,
  companyId: companyId,
  ...((country || city || postalCode || street) && {
    address: {
      ...(country && { country }),
      ...(city && { city }),
      ...(postalCode && { postalCode }),
      ...(street && { street }),
    },
  }),
};

Jadi ini menimbulkan pertanyaan, apakah ini hanya skenario "pilih racunmu"? Skenario terakhir misalnya, Anda menulis kode untuk merusak dan memberi nama properti sebelum membuat objek, dan kemudian di dalam objek, kodenya lebih sederhana dan lebih mudah dibaca?

Dan ini membawa saya ke pertanyaan lain, pengoptimalan yang saya cari, apakah itu sesuatu yang layak diselidiki sama sekali, atau tetap berpegang pada salah satu skenario ini baik-baik saja?

2
Darkbound 10 Januari 2021, 21:31

3 jawaban

Jawaban Terbaik

Saya pikir Anda telah mengoptimalkan panjang kode Anda sejauh mungkin dengan destrukturisasi. Cara lain untuk menyimpan kode adalah menggunakan fungsi utilitas (yang saya sarankan karena sihir perusakan seperti itu rentan terhadap kesalahan ketik jika Anda sering melakukannya).

Fungsi utilitas berikut akan memungkinkan Anda memilih nilai dengan cara yang lebih deklaratif, memastikan bahwa tidak ada nilai tambahan dan grup kosong dihilangkan. Hanya varian dari fungsi atas (yang agak pendek dan cukup jelas) yang diperlukan untuk setiap formulir yang Anda buat.

const handleAddSupplier = (e) => {
  e.preventDefault();
  const values = formToValues(e.target);
  const supplierData = {
    ...pickFrom(values, ["name", "companyId"]),
    ...optionalGroupFrom(values, "address", [
      "country",
      "city",
      "postalCode",
      "street",
    ]),
  };
  console.log(supplierData);
};


// Utility functions (you can import them from another file)

function formToValues(form) {
  const elements = form.elements;
  const values = {};
  for (const name in elements)
    if (elements[name].value) values[name] = elements[name].value;
  return values;
}

const optionalGroupFrom = (values, name, keys) => {
  const group = pickFrom(values, keys);
  const hasKeys = Object.keys(group).length !== 0;
  if (hasKeys) return {
    [name]: group
  };
  else return null;
};

const pickFrom = (values, keys) =>
  keys
  .map((key) => ({
    key,
    value: values[key]
  }))
  .filter((pair) => pair.value !== undefined)
  .reduce((map, pair) => {
  console.log( map );
    map[pair.key] = pair.value;
    return map;
  }, {});
<form onsubmit="handleAddSupplier(event); return false;">
  <input type="text" name="name" /> name<br />
  <input type="text" name="companyId" /> companyId<br />
  <input type="text" name="country" /> country<br />
  <input type="text" name="city" /> city<br />
  <input type="text" name="postalCode" /> postalCode<br />
  <input type="text" name="street" /> street<br />
  <input type="submit" value="Submit" />
</form>
2
soimon 10 Januari 2021, 19:22

Anda dapat memeriksanya dalam lingkaran

function process(e) {
  let obj = {}
  for(let item of e.target.elements){
    if(item.value) obj[item.name]=item.value //should do proper check if it's can have valid falsy value, I leave it here for simplicity
  }
  console.log(obj)
}
<form onsubmit="process(event);return false;">
  <div>
    <label for=a>A: </label>
    <input type=text name=a>
  </div>
  <div>
    <label for=b>B: </label>
    <input type=text name=b>
  </div>
  <div>
    <button type="submit">OK</button>
  </div>
</form>

5
apple apple 10 Januari 2021, 19:24

Inilah solusi yang panjangnya cukup mirip tetapi saya pikir ini:

  1. lebih mudah dibaca
  2. skala tanpa rasa sakit dengan bidang opsional baru
const handleAddSupplier = (e) => {
    e.preventDefault();
    const { name, companyId, country, city, postalCode, street } = e.target.elements;

    const supplierData = {
      name: formData.name.value,
      companyId: formData.companyId.value
    };

    const address = {
        country: (country || {}).value,
        city: (city || {}).value,
        postalCode: (postalCode || {}).value,
        street: (street || {}).value
    };
    Object.keys(address).forEach(key => {
        if (!address[key]) {  // Will catch null or undefined
            delete address[key];
        }
    });

    if (Object.keys(address).length) {
        supplierData.address = address;
    }
    console.log(supplierData);
  };
0
kingkupps 10 Januari 2021, 19:04