前面幾天順著 Component、資料流、表單與 localStorage,慢慢理解 AI 產生的專案。
目前主要功能都可以正常使用:
既然功能都能使用,是不是就代表 AI 寫得很好,完全不用再檢查?
當然還是要。如果沒有閱讀並檢查目前的內容,就永遠不會知道自己讓 AI 做了些什麼;萬一之後需要修改某個小地方,也不會知道第一時間該怎麼改、要從哪個檔案開始找。
一開始可能會以為只是檢查程式碼有沒有寫錯。但除了能不能執行,還可以注意:
所以「能跑」只是其中一項結果,不代表其他部分一定都沒有問題。
目前專案可以執行:
npm run lint
執行後沒有出現錯誤。
Lint 可以協助檢查不符合規則的寫法,以及部分可能出錯的內容。至少從這項結果來看,目前程式碼沒有被工具發現明顯問題。
不過,Lint 通過也不代表功能與邏輯一定正確,它比較像是第一層檢查,而不是最後答案。
重新閱讀專案後,還是可以先看到一些安排得不錯的地方。
例如,主要收藏資料集中在 App:
const [items, setItems] =
useState<CollectionEntry[]>(loadItems)
表單自己的 State 則留在 AddItemForm,和 Day 22 整理出的資料放置方式一致。
更新陣列時,也沒有直接修改原本的 State:
setItems((currentItems) => [newItem, ...currentItems])
刪除與修改則使用 filter() 和 map() 建立新陣列,符合 Day 11 認識的 State 更新方式。
所以 Code Review 並不是只為了挑錯,也要確認哪些地方目前已經安排得算合理。
在 storage.ts 中,loadItems() 標示自己會回傳 CollectionEntry[]:
export function loadItems(): CollectionEntry[] {
try {
const savedItems = localStorage.getItem(STORAGE_KEY)
return savedItems ? JSON.parse(savedItems) : []
} catch {
return []
}
}
第一眼看起來沒有問題:找到資料就使用 JSON.parse() 還原,失敗就回傳空陣列。
但 TypeScript 的型別只會在開發階段提供檢查,不會在程式執行時自動確認外部資料。
所以:
JSON.parse(savedItems)
雖然被當成 CollectionEntry[] 回傳,卻沒有真的檢查讀到的內容是不是陣列,也沒有確認每筆資料是否包含 id、title、type 和 status。
如果 localStorage 裡存的是:
"這不是收藏陣列"
它仍然是正確的 JSON,所以 JSON.parse() 不會失敗。但還原後得到的是字串,不是 CollectionEntry[],之後執行 items.map() 時就可能發生錯誤。
目前的 try...catch 可以處理 JSON 無法解析的情況,卻不能確認解析成功後的資料格式是否正確。
這不一定代表 AI 寫錯了,而是這段程式碼假設 localStorage 裡一定存放著專案自己產生的正確資料。
對目前的練習專案來說,這種處理方式可能暫時足夠;但如果希望程式更穩定,就可以增加資料格式的檢查。
找到這個問題後,也不用立刻叫 AI 修改,可以先問它:
請檢查
loadItems()是否有確認JSON.parse()後的資料符合CollectionEntry[]。如果沒有,請說明可能發生什麼問題,以及可以如何改善。先不要修改程式碼。
先讓 AI 說明問題與解法,再判斷是否需要修改,比直接接受它產生的新程式碼更容易掌握變化。
localStorage 讀出的資料try...catch 能處理解析失敗,但不能保證資料格式正確AI 寫出的第一版確實可以正常操作,但「功能能用」和「所有情況都有處理好」並不是同一件事。
至少這次不再只是看到畫面能動就直接接受,而是開始試著找出程式碼背後做了哪些假設。
下篇見!