在你崩潰之前,這8種做法會讓React應用程序先崩潰
React庫的優勢非常明顯:創建復雜的交互用戶界面非常簡單。最大的特點是可以在不破壞其他組件的情況下,將組件直接組合在一起。即使是Facebook、Instagram、Pinterest這樣的社交媒體巨頭也大量使用React,同時通過谷歌Maps這樣的大型API創造無縫的用戶體驗。
如果你正在用React構建一個應用程序,或是考慮將其用于即將開展的項目,那么本教程就是為你準備的。希望通過公開一些需要再三考慮的代碼執行,來幫助你構建出色的React應用程序。
下面是React里會使應用程序崩潰的八種做法:
1. 在null上設置默認參數
這是一個令人毛骨悚然的陷阱,可以讓開發人員全線崩潰。畢竟,應用程序崩潰不是小事——任何類型的崩潰如果處理不當,隨時都可能導致資金損失。
比如:
在應用程序組件中,如果日期最終是falsey,它將初始化為null。直覺告訴我們,在默認情況下,當項是一個falsey值時,應該將其初始化為空數組。但是當日期為falsey時,應用程序會崩潰,因為條目為空。
如果沒有傳遞值或者未定義的值,那么默認函數參數允許使用默認值初始化已命名參數!
因此,下次將默認值設置為null時,一定要三思而后行。當空數組是值的預期類型時,可以將值初始化為空數組。
2. 用方括號抓取屬性
有時抓取屬性的方式可能會影響到應用程序的行為。也就是說會造成應用程序崩潰。下面是一個用方括號執行對象查找的例子:
這些實際上都是100%有效的用例,除了比對象鍵查找慢之外,實際上沒有任何問題。無論如何,隨著查找的深入,應用程序里也會出現問題:
如果你對此代碼段實施某些增強并犯了一個小錯誤(例如將j中的J大寫),結果將立即返回undefined,并且會發生崩潰:
令人毛骨悚然的部分是,應用程序會直到一部分代碼嘗試使用未定義值進行屬性查找時才會崩潰。
所以在同一時間,joesProfile(經過偽裝的未定義)將在應用程序運行,沒有人會知道這個未定義值正在蔓延,直到一段代碼執行屬性查找,如joesProfile.age,因為joesProfile未定義!
為避免崩潰,一些開發人員會在查找不成功時初始化一些默認有效返回值:
至少現在,應用程序沒有崩潰。這說明,當你使用方括號表示法應用查找時,往往是無效的。
然而,如果沒有實際的例子,很難解釋這種做法的嚴重性。所以,接下來我們舉一個真實的例子。以將要展示的這個代碼示例為例,它可以追溯到8個月前的存儲庫。為了保護這個代碼來源的一些隱私,我們重名了幾乎所有的變量,但是代碼設計、語法和架構完全一樣:
fixVideoTypeNaming是一個函數,它將根據作為參數傳入的值提取視頻類型。如果參數是一個視頻對象,它將從.videoType屬性中提取視頻類型。如果是字符串,則調用者傳入videoType,這樣就可以跳過第一步。有人發現視頻類型.mp4property在應用程序的幾塊地方都被拼錯了。用fixVideoTypeNaming來快速修補這個錯誤。
現在,這個應用程序是用Redux構建的——因此語法。
要使用這些選擇器,你可以導入到connect高階組件中,以附加一個組件來偵聽狀態的那部分。
UI組件
該組件接收HOC傳遞給它的所有屬性,并顯示適應屬性里的數據的信息。理想狀態下可行,現實中只是暫時可行。 如果回到容器中,看看選擇器是怎么選擇它們的值的,其實可能已經埋下了一個定時炸彈,正在等著爆炸:
在開發任何類型的應用程序時,為了確保較高的可信度和減少開發流程中的漏洞,一般在開發過程中進行測試,以保證應用程序按預期運行。 然而,在這些代碼片段的案例中,如果沒有經過測試,而且沒有及早處理,應用程序就會崩潰。例如,state、app、media、video、videoType是鏈的四個層次。
如果一個開發人員在修復應用程序的另一部分時不小心出錯了,而state、app、media、video變成未定義狀態,那么應用程序將崩潰,因為它無法讀取未定義的videoType的屬性。
此外,如果videoType出現了另外一個錯誤,而fixVideoTypeNaming沒有更新以適應mp3的問題,那么該應用程序將面臨另一個意外崩潰的風險。而這除非發生在真實的用戶身上,否則沒人能夠檢測到它。那時就為時已晚了。 絕不可以僥幸認為應用程序永遠不會碰到這樣的漏洞。請小心點!
3. 渲染時粗心地檢查空對象
在過去有條件地渲染組件的黃金時期,有人曾做過一件事,那就是檢查數據是否使用Object.keys填充到對象中。如果有數據,那么如果條件通過,組件將繼續渲染。
假設調用了某個API,并在響應的某個地方接收了作為對象的項。話雖如此,乍一看似乎完全沒有問題。項目的預期類型是對象,所以用Object.keys完全沒問題。畢竟,如果出現錯誤并轉化為falsey值,的確可以通過把項初始化為空對象來進行防御。
但服務器不總是返回相同的結構。如果將來項變成數組會怎樣?Object.keys(items)不會崩潰,但會返回一個奇怪的輸出,比如[“0”、“1”、“2”]。被該數據渲染的組件該如何反應呢?
但這還不是最糟的部分。代碼片段中最糟的是,如果屬性里收到的項是空值,那么項甚至不會初始化為默認值。
那么在開始使用應用程序前,就崩潰了:
再說一遍,請小心點!
4. 在渲染前粗心地檢查數組是否存在
這可能和第3條的情況非常相似,但是數組和對象經常可以互換使用,所以應該單列出來。
如果你有這樣做的習慣:
那么至少確保有單元測試,始終密切關注這段代碼,或者在傳遞給渲染函數前及早正確地處理arr,否則如果arr變成對象文字,應用程序就會崩潰。當然, &&操作符會認為它是真實的,并嘗試.map對象文字,這最終導致整個應用程序的崩潰。
所以請牢記于心。節省你的精力以及挫敗感,把它留給更值得你特別關注的大問題吧!
5. 沒有使用Linter
如果在開發應用程序時,沒有使用任何類型的linter,或者根本不知道它們是什么,你必須知道為什么它們在開發中很有用。
用來輔助開發流程的linter是ESLint(https://eslint.org/?source=post_page---------------------------),這是一個著名的JavaScript的linting工具,它允許開發人員在不執行代碼的情況下發現問題。
這個工具非常有用,它就像半個導師一樣,及時糾正錯誤——就好像有人在指導你一樣。它甚至描述了為什么你的代碼可能是錯誤的,并建議你應該做什么。
這里有一個例子:
關于ESLint最酷的是,如果不喜歡某些規則或是不同意其中的一些規則,可以禁用這些規則,這樣它們就不會在開發時顯示為 linting警告/錯誤了。
6. 在渲染列表時進行解構
過去有些人出現過這種情況,而且很難檢測到漏洞。基本上,如果有一個項目列表,并且準備渲染每個項目的一堆組件,如果列表中有一個項目不是期待值,那么應用程序會出現漏洞。如果應用程序不知道如何處理值類型,就有可能會崩潰。
這里有一個例子:
代碼可以成功地運行。來看看API調用,而不是返回這個——
——如果在API客戶端出現了意外情況并且返回這個數組時,如何解決這個問題呢?
那么應用程序就會崩潰,因為它不知道如何處理:
- Uncaught TypeError: Cannot read property 'name' of undefined
- at eval (DataList.js? [sm]:65)
- at Array.map (<anonymous>)
- at DataList (DataList.js? [sm]:64)
- at renderWithHooks (react-dom.development.js:12938)
- at updateFunctionComponent (react-dom.development.js:14627)
所以為了防止應用崩潰,可以在每次迭代中都設置一個默認對象:
現在,用戶不會再對你的技術和專業知識評頭論足了,因為他們不會再看到頁面崩潰的情況了:
然而,即使應用不再崩潰,建議進一步處理缺失值,比如為具有類似問題的整個項目返回null,因為其中沒有任何數據。
7. 沒有充分研究你要實施的東西
不少人曾犯過這個致命的錯誤:對自己實施的搜索輸入過度自信,過早相信自己的觀點。
這是什么意思呢?搜索輸入這一部分本應是個簡單的任務——而且的確如此。整個搜索功能出現問題的真正原因是在查詢中包含字符。
如果將關鍵字作為查詢發送到搜索API,僅僅認為用戶鍵入的每個鍵是有效的是不夠的,即使是因為它們都在鍵盤上。
只要100%確保這樣的正則表達式完全按預期運行,并避免遺漏任何可能使應用崩潰的無效字符:
該示例是搜索API最新的、既定的正則表達式。 以前它是這樣的:
可以看到斜杠/不見了,而這導致了應用崩潰!如果該字符最終通過網絡發送到API,猜猜API會如何處理URL?
另外,不要完全相信在網上找到的例子。其中有許多都不是經過充分測試的解決方案。而且就正則表達式而言,大多數用例沒有真正的標準。
8. 不限制文件輸入的大小
限制用戶選擇的文件大小是很好的做法,因為大多數情況下,如果不會出現任何品質損失,可以對大文件進行壓縮。
但關于為什么把文件大小限制在某個限度內,還有一個更重要的原因。在公司里,用戶上傳圖片時偶爾會被“凍結”。并不是每個人都有Alienware 17 R5電腦,所以必須考慮用戶的特殊情況。
你不會希望用戶在本應上傳文件的時候卻上傳電子游戲吧?
以下是將文件限制為5 MB(5,000,000字節)限制的示例: