logo-Chiyu

Chiyu

Blog

Here I share my stories.

React 怎麼用 slice() 修改 Array of Objects?

而且只用一行解決唷~!

🕒 published on ー 2022. 2. 11.

thumbnail.png

Photo by Matt Pero on Unsplash

Free Talk

曾遇過某前端主管,主張凡事 Code 寫越少行才是越好,只用一行就解決問題才是最專業、最資深。

可是我以為 Code 好壞,是看時間複雜度跟空間複雜度判斷吧 (´・ω・`)

在 LeetCode,我 TwoSum 寫了 11 行的 Hash Map 解法跑 48 豪秒,寫了 9 行的雙迴圈解法要跑 108 豪秒,可別跟我說這樣也是行數少的好唷…w?

行數,自然是能少就少,但實在不能苟同那某前端主管那樣武斷的主張。再說,若是少到沒有可讀性可言,也稱不上好。

什麼時候會用到這招?

例如要實現以下畫面跟修改功能的時候!

update-an-array-of-objects.gif

Image by Chiyu

一步步來分析
  1. 要處理的資料是個 Array,Array 裡的每個 Item 都是一個 Object,也就是文章標題所說的 Array of Objects。
  2. 只需要修改裡面其中一個 Object 某個 Field 的 Value。
  3. 但你是 React 系的,要遵守 immutable 原則,不可直接修改原本的 Array。
  4. 最好只用一行解決,不然某前端主管會認定你不專業、嫌你寫得落落長,然後退你的 Merge Request,說因為你不資深所以他懶得 Code Review。

開始出招!

首先 slice() 的用法可以參考 [JavaScript] slice()、splice()、split() 傻傻分不清 這篇。

假設要處理的資料是一個貓貓 Array,記錄了 5 隻貓貓的姓名、品種:

[
  { id: '1', name: '糰子', breed: 'Birman' },
  { id: '2', name: '柳丁', breed: 'American Shorthair' },
  { id: '3', name: '花醬', breed: 'Japanese Bobtail' },
  { id: '4', name: '阿灰', breed: 'Russian Blue' },
  { id: '5', name: 'Kiki', breed: 'Bengal' },
];

這邊為了方便文章解說,我會直接將資料寫在 useState() 裡,真實情況,資料可能要先 Call 個 API 取得,或是用 Redux 那套,這部分相信請各位有能力融會貫通。

那我們整個 Code 就可以這樣寫!

const MyComponent = () => {
  const [cats, setCats] = useState([
    { id: '1', name: '糰子', breed: 'Birman' },
    { id: '2', name: '柳丁', breed: 'American Shorthair' },
    { id: '3', name: '花醬', breed: 'Japanese Bobtail' },
    { id: '4', name: '阿灰', breed: 'Russian Blue' },
    { id: '5', name: 'Kiki', breed: 'Bengal' },
  ]);

  return (
    <div className="grid">
      <div className="header">Cats</div>
      {cats?.length > 0 &&
        cats.map((cat, index) => (
          <div className="row">
            <div className="col">{cat.id}</div>
            <div className="col">
              <input
                value={cat.name}
                onChange={(e) => {
                  setCats([...cats.slice(0, index), { ...cat, name: e.target.value }, ...cats.slice(index + 1)]);
                }}
              />
            </div>
            <div className="col">{cat.breed}</div>
            <div className="col">
              <button>修改</button>
            </div>
          </div>
        ))}
    </div>
  );
};

各位呀,就是關鍵的這一行!幫我們施展了魔術,名為跟 Spread Operator 的組合技!

setCats([...cats.slice(0, index), { ...cat, name: e.target.value }, ...cats.slice(index + 1)]);

簡單說就是複製原 Array → 切頭 → 複製目標物 → 修改 → 複製原 Array 切尾 → 通通拚回去,如果是用 Redux 那套,這行邏輯我會改寫在 reducer 裡(把 index新名字 當作 payload,dispatch action 到 reducer 裡面作業)。

Ending

好的,我可是寫出了某前端主管認為專業又資深的 Code 了唷,猜猜最後他怎麼說?

他說其實他想要看到的是我用 find() 找到 index 後再接 map() 去改目標物啦哈哈哈

意思是我用了他不習慣的方法,所以縱使我早已通過試用期許久,是正職的前端工程師,還在團隊並沒有訂定這方面規範也無提示的情況下,自立自強獨立解決了這個問題,在他眼裡還是不專業不資深的唷 (´・ω・`)

真是幸好已離開那間公司,不知道他們之後有沒有在前端 JD 補上需要會通靈這個條件呢,以上分享自己的做法兼說說爛事系列 w

Copyright © 2022 Chiyu