React 怎麼用 slice() 修改 Array of Objects?
而且只用一行解決唷~!
🕒 published on ー 2022. 2. 11.
Photo by Matt Pero on Unsplash
Free Talk
曾遇過某前端主管,主張凡事 Code 寫越少行才是越好,只用一行就解決問題才是最專業、最資深。
可是我以為 Code 好壞,是看時間複雜度跟空間複雜度判斷吧 (´・ω・`)
在 LeetCode,我 TwoSum 寫了 11 行的 Hash Map 解法跑 48 豪秒,寫了 9 行的雙迴圈解法要跑 108 豪秒,可別跟我說這樣也是行數少的好唷…w?
行數,自然是能少就少,但實在不能苟同那某前端主管那樣武斷的主張。再說,若是少到沒有可讀性可言,也稱不上好。
什麼時候會用到這招?
例如要實現以下畫面跟修改功能的時候!
Image by Chiyu
一步步來分析
- 要處理的資料是個 Array,Array 裡的每個 Item 都是一個 Object,也就是文章標題所說的 Array of Objects。
- 只需要修改裡面其中一個 Object 某個 Field 的 Value。
- 但你是 React 系的,要遵守 immutable 原則,不可直接修改原本的 Array。
- 最好只用一行解決,不然某前端主管會認定你不專業、嫌你寫得落落長,然後退你的 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